home *** CD-ROM | disk | FTP | other *** search
- /*
- * CheckGuide.c, A tool to check the consistency of AmigaGuide databases
- *
- * Copyright © 1997 by Olaf Barthel <olsen@sourcery.han.de>
- * All Rights Reserved
- *
- * :ts=4
- */
-
- #include <exec/lists.h>
- #include <exec/nodes.h>
-
- #include <dos/dosextens.h>
- #include <dos/rdargs.h>
-
- #include <clib/exec_protos.h>
- #include <clib/dos_protos.h>
- #include <clib/alib_protos.h>
-
- #ifdef __SASC
- #include <pragmas/exec_sysbase_pragmas.h>
- #include <pragmas/dos_pragmas.h>
- #endif /* __SASC */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <signal.h>
-
- /****************************************************************************/
-
- #define SAME (0)
- #define NOT !
- #define CANNOT !
-
- /****************************************************************************/
-
- void FreeList(struct List *list);
- struct Node *FindIName(const struct List *list, const char *name);
- struct EntryNode *CreateNode(const char *name);
- BOOL IsNumber(const char *s);
- VOID CollectNodes(const char *file, struct List *list);
- struct DatabaseNode *RegisterFile(struct List *list, BPTR lock);
- struct DatabaseNode *LocateNode(const char *parentFileName, const char *thisFileName, int line, const char *linkFileName);
- void CheckGuide(const char *file, const char *parentFile, FILE *in);
- int main(int argc, char **argv);
-
- /****************************************************************************/
-
- STRPTR version = "$VER: CheckGuide 1.8 (21.8.97)";
-
- /****************************************************************************/
-
- extern struct Library *SysBase;
- extern struct Library *DOSBase;
-
- /****************************************************************************/
-
- struct EntryNode
- {
- struct Node Node;
- long line;
- long references;
- struct EntryNode * within;
- };
-
- struct DatabaseNode
- {
- struct Node Node;
- struct List nodes;
- BOOL collected;
- BOOL checked;
- };
-
- /****************************************************************************/
-
- #define LINK "@{"
- #define OPEN_BRACE '{'
- #define CLOSE_BRACE '}'
-
- /****************************************************************************/
-
- const char *keywords[][2] =
- {
- "@database", "1NAME/A",
- "@author", "1NAME/F",
- "@(c)", "1NAME/F",
- "@$VER: ", "1NAME/F",
- "@master", "1NAME/A",
- "@font", "1NAME/A,2SIZE/N/A",
- "@index", "1NAME/A",
- "@help", "1NAME/A",
- "@onopen", "1NAME/F",
- "@onclose", "1NAME/F",
- "@proportional", NULL,
- "@wordwrap", NULL,
- "@smartwrap", NULL,
- "@node", "1NAME/A,2TITLE",
- "@dnode", "1NAME/A,2TITLE",
- "@remark", NULL,
- "@rem", NULL,
- "@title", "1TITLE/A/F",
- "@toc", "1NAME/A",
- "@macro", "1NAME/A,2NAME/A",
- "@prev", "1NAME/A",
- "@xref", "1NAME/A",
- "@next", "1NAME/A",
- "@width", "1NAME/A/N",
- "@height", "1NAME/A/N",
- "@tab", "1NAME/A/N",
- "@keywords", "1KEYWORDS/A/M",
- "@endnode", NULL,
- LINK, "1LABEL/A,2COMMAND/A/F",
- NULL
- };
-
- /****************************************************************************/
-
- struct List CheckedFileList;
- BOOL Recursive = FALSE;
- BOOL OnlyGuideFiles = FALSE;
- BOOL Warnings = TRUE;
-
- /****************************************************************************/
-
- void
- FreeList(struct List *list)
- {
- struct Node *node;
-
- while((node = RemHead(list)) != NULL)
- free(node);
- }
-
- struct Node *
- FindIName(
- const struct List * list,
- const char * name)
- {
- struct Node *node;
-
- for(node = list->lh_Head ; node->ln_Succ ; node = node->ln_Succ)
- {
- if(stricmp(node->ln_Name,name) == SAME)
- return(node);
- }
-
- return(NULL);
- }
-
- struct EntryNode *
- CreateNode(const char *name)
- {
- struct EntryNode * node;
-
- node = (struct EntryNode *)malloc(strlen(name)+1 + sizeof(*node));
- if(node != NULL)
- {
- memset(node,0,strlen(name)+1 + sizeof(*node));
- strcpy(node->Node.ln_Name = (char *)(node + 1),name);
- }
- else
- {
- perror("CheckGuide");
- exit(RETURN_FAIL);
- }
-
- return(node);
- }
-
- /****************************************************************************/
-
- BOOL
- IsNumber(const char *s)
- {
- int len = strlen(s);
-
- if(len == 0)
- {
- return(FALSE);
- }
- else
- {
- int i;
-
- for(i = 0 ; i < len ; i++)
- {
- if(s[i] < '0' || s[i] > '9')
- return(FALSE);
- }
-
- return(TRUE);
- }
- }
-
- /****************************************************************************/
-
- VOID
- CollectNodes(
- const char * file,
- struct List * list)
- {
- FILE *in;
-
- /* This file *must* exist. */
- in = fopen(file,"r");
- if(in != NULL)
- {
- static char buffer[1024];
- int i,len,line;
-
- line = 0;
-
- /* Two characters less to allow for line termination characters. */
- while(fgets(buffer,sizeof(buffer)-2,in) != NULL)
- {
- /* Strip trailing line feed. */
- len = strlen(buffer);
- if(len > 0 && buffer[len - 1] == '\n')
- buffer[--len] = '\0';
-
- /* If this is the first line, it must have the
- * @database keyword in it (if this is an AmigaGuide
- * database, that is).
- */
- line++;
- if(line == 1 && strnicmp(buffer,"@database",9))
- {
- const char *main = "main";
- struct Node *node;
-
- /* A "main" node is always available, so to speak. */
- node = (struct Node *)malloc(sizeof(*node) + strlen(main)+1);
- if(node != NULL)
- {
- strcpy(node->ln_Name = (char *)(node + 1),main);
- AddTail(list,node);
- }
- else
- {
- perror("CheckGuide");
- exit(RETURN_FAIL);
- }
-
- break;
- }
-
- /* If this line carries a @node keyword, analyze
- * it. We want to keep the node name.
- */
- if(strnicmp(buffer,"@node",5) == SAME)
- {
- int quote = 0;
- BOOL gotNodeName = FALSE;
- char *skip = &buffer[5];
-
- while(*skip == ' ' || *skip == '\t')
- skip++;
-
- len = strlen(skip);
-
- /* Flatten all escape characters. */
- for(i = 0 ; i < len ; i++)
- {
- if(skip[i] == '\\' && i < len-1)
- {
- skip[i] = '-';
- skip[i+1] = '-';
- }
- }
-
- /* So the following search will always terminate. */
- strcat(skip," ");
- len++;
-
- /* Look for the node name. */
- for(i = 0 ; i < len ; i++)
- {
- if(skip[i] == '\"')
- quote ^= 1;
-
- /* The search stops at a blank space. */
- if(skip[i] == ' ' || skip[i] == '\t')
- {
- if(quote == 0)
- {
- skip[i] = '\0';
- gotNodeName = TRUE;
- break;
- }
- }
- }
-
- /* If we got a node name, check if it contains
- * space characters (it must not).
- */
- if(gotNodeName)
- {
- len = strlen(skip);
-
- for(i = 0 ; i < len ; i++)
- {
- if(skip[i] == ' ' || skip[i] == '\t')
- {
- gotNodeName = FALSE;
- break;
- }
- }
- }
-
- /* If this is still a valid node name, strip
- * any quote characters and add it to the list.
- */
- if(gotNodeName)
- {
- struct Node *node;
- int j;
-
- for(i = 0, j = 0 ; i < len ; i++)
- {
- if(skip[i] != '\"')
- buffer[j++] = skip[i];
- }
-
- buffer[j] = '\0';
-
- node = (struct Node *)malloc(sizeof(*node) + strlen(buffer)+1);
- if(node != NULL)
- {
- strcpy(node->ln_Name = (char *)(node + 1),buffer);
- AddTail(list,node);
- }
- else
- {
- perror("CheckGuide");
- exit(RETURN_FAIL);
- }
- }
- }
- }
-
- fclose(in);
- }
- }
-
- struct DatabaseNode *
- RegisterFile(
- struct List * list,
- BPTR lock)
- {
- char localBuffer[400];
- struct DatabaseNode * result = NULL;
-
- if(NameFromLock(lock,localBuffer,sizeof(localBuffer)))
- {
- result = (struct DatabaseNode *)FindIName(list,localBuffer);
- if(result == NULL)
- {
- result = (struct DatabaseNode *)malloc(sizeof(*result) + strlen(localBuffer)+1);
- if(result != NULL)
- {
- strcpy(result->Node.ln_Name = (char *)(result + 1),localBuffer);
- NewList(&result->nodes);
- result->checked = FALSE;
- result->collected = FALSE;
-
- AddTail(list,(struct Node *)result);
- }
- else
- {
- perror("CheckGuide");
- exit(RETURN_FAIL);
- }
- }
- }
-
- return(result);
- }
-
- struct DatabaseNode *
- LocateNode(
- const char * parentFileName,
- const char * thisFileName,
- int line,
- const char * linkFileName)
- {
- char fileName[400];
- char *nodeName;
- struct DatabaseNode *result = NULL;
-
- nodeName = FilePart((STRPTR)linkFileName);
- if(nodeName != linkFileName)
- {
- struct Process *thisProcess = (struct Process *)FindTask(NULL);
- APTR oldPtr = thisProcess->pr_WindowPtr;
- BPTR lock;
- BOOL relativePath = FALSE;
-
- strcpy(fileName,linkFileName);
- *PathPart(fileName) = '\0';
-
- thisProcess->pr_WindowPtr = (APTR)-1;
-
- lock = Lock(fileName,SHARED_LOCK);
- if(lock == NULL)
- {
- strcpy(fileName,parentFileName);
- *PathPart(fileName) = '\0';
- if(AddPart(fileName,(STRPTR)linkFileName,sizeof(fileName)))
- {
- *PathPart(fileName) = '\0';
-
- lock = Lock(fileName,SHARED_LOCK);
- relativePath = TRUE;
- }
- }
-
- thisProcess->pr_WindowPtr = oldPtr;
-
- if(lock != NULL)
- {
- struct DatabaseNode *node;
-
- node = RegisterFile(&CheckedFileList,lock);
- result = node;
-
- UnLock(lock);
-
- if(relativePath && Warnings)
- printf("%s:%d:File found in relative path only \"%s\"\n",thisFileName,line,fileName);
-
- if(node != NULL)
- {
- if(NOT node->collected)
- {
- CollectNodes(node->Node.ln_Name,&node->nodes);
- node->collected = TRUE;
- }
-
- if(CANNOT FindIName(&node->nodes,nodeName))
- {
- result = NULL;
- }
- }
- }
- }
-
- return(result);
- }
-
- /****************************************************************************/
-
- void
- CheckGuide(
- const char * file,
- const char * parentFile,
- FILE * in)
- {
- static char buffer[1024];
- static char localBuffer[1000];
- int line,len;
- struct EntryNode *lastNode = NULL;
- struct EntryNode *node, *mainFound;
- char plainName[400];
- int i,j;
- char *suffix = "guide";
- struct List NodeList;
- struct List IndexList;
- struct List TocList;
- struct RDArgs *rdargs;
- int underlineCol = -1,underlineRow = -1;
- int boldCol = -1,boldRow = -1;
- int italicsCol = -1,italicsRow = -1;
-
- NewList(&NodeList);
- NewList(&IndexList);
- NewList(&TocList);
-
- strcpy(plainName,FilePart((STRPTR)file));
- for(j = strlen(plainName) - 1 ; j >= 0 ; j--)
- {
- if(stricmp(&plainName[j],".hyper") == SAME)
- {
- if(Warnings)
- printf("%s:%d:File uses obsolete .hyper name suffix\n",file,1);
-
- plainName[j] = '\0';
- suffix = &plainName[j+1];
- break;
- }
-
- if(stricmp(&plainName[j],".guide") == SAME)
- {
- plainName[j] = '\0';
- suffix = &plainName[j+1];
- break;
- }
- }
-
- line = 0;
-
- while(fgets(buffer,sizeof(buffer)-1,in) != NULL)
- {
- line++;
-
- len = strlen(buffer);
- if(len > 0 && buffer[len - 1] == '\n')
- buffer[--len] = '\0';
-
- if(line == 1)
- {
- if(strnicmp(buffer,"@database",9))
- {
- if(OnlyGuideFiles && Recursive)
- return;
-
- printf("%s:%d:First line must contain @database keyword\n",file,line);
- }
- }
-
- for(i = 0 ; i < len ; i++)
- {
- if(buffer[i] == '@' && buffer[i+1] == '@')
- {
- buffer[i] = buffer[i+1] = ' ';
- }
-
- if(buffer[i] == '\\' && i < len-1)
- {
- buffer[i] = buffer[i+1] = '-';
- }
- }
-
- if(buffer[0] == '@')
- {
- char const *found = NULL;
-
- for(i = 0 ; keywords[i][0] != NULL ; i++)
- {
- if(strnicmp(buffer,keywords[i][0],strlen(keywords[i][0])) == SAME)
- {
- found = keywords[i][0];
- break;
- }
- }
-
- if(NOT found)
- {
- char key[40];
-
- strncpy(key,buffer,19);
- key[19] = '\0';
- printf("%s:%d:Unknown keyword \"%s\"\n",file,line,key);
- }
- else
- {
- if(keywords[i][1] != NULL)
- {
- long args[2] = { NULL,NULL };
-
- signal(SIGINT,SIG_IGN);
-
- rdargs = AllocDosObjectTagList(DOS_RDARGS,NULL);
- if(rdargs != NULL)
- {
- char *rest;
- int k;
-
- strcat(buffer,"\n");
-
- rest = buffer + strlen(keywords[i][0]);
-
- while(*rest == ' ')
- rest++;
-
- rdargs->RDA_Source.CS_Buffer = rest;
- rdargs->RDA_Source.CS_Length = strlen(rdargs->RDA_Source.CS_Buffer);
- rdargs->RDA_Source.CS_CurChr = 0;
- rdargs->RDA_Flags = RDAF_NOPROMPT;
-
- for(k = 0 ; k < strlen(rest) ; k++)
- {
- if(rest[k] == '*') /* This confuses the ReadArgs() parser. */
- rest[k] = '+';
- }
-
- if(ReadArgs((char *)keywords[i][1],args,rdargs))
- {
- if(strcmp(found,"@node") == SAME || strcmp(found,"@dnode") == SAME)
- {
- if(lastNode != NULL)
- {
- printf("%s:%d:Unbalanced @node\n",file,lastNode->line);
- }
-
- lastNode = CreateNode((char *)args[0]);
- if(lastNode != NULL)
- {
- struct Node *node;
-
- lastNode->line = line;
-
- for(node = NodeList.lh_Head ; node->ln_Succ ; node = node->ln_Succ)
- {
- if(stricmp(node->ln_Name,(char *)args[0]) == SAME)
- {
- printf("%s:%d:Duplicate @node \"%s\" (see line %d)\n",file,line,node->ln_Name,((struct EntryNode *)lastNode)->line);
- break;
- }
- }
-
- AddTail(&NodeList,(struct Node *)lastNode);
- }
- }
-
- if(strcmp(found,"@database") == SAME)
- {
- char otherPlainName[400];
- char *otherSuffix = "guide";
- int j;
-
- strcpy(otherPlainName,FilePart((char *)args[0]));
- for(j = strlen(otherPlainName) - 1 ; j >= 0 ; j--)
- {
- if(stricmp(&otherPlainName[j],".guide") == SAME)
- {
- otherPlainName[j] = '\0';
- otherSuffix = &otherPlainName[j+1];
- break;
- }
-
- if(stricmp(&otherPlainName[j],".hyper") == SAME)
- {
- otherPlainName[j] = '\0';
- otherSuffix = &otherPlainName[j+1];
-
- if(Warnings)
- printf("%s:%d:Database name uses obsolete .hyper suffix\n",file,line,found);
-
- break;
- }
- }
-
- if(Warnings)
- {
- if(stricmp(suffix,otherSuffix))
- printf("%s:%d:Database \"%s\" and file name \"%s\" suffixes do not match\n",file,line,suffix,otherSuffix);
- else
- {
- if(stricmp(otherPlainName,plainName))
- printf("%s:%d:Database \"%s\" and file name \"%s\" do not match\n",file,line,otherPlainName,plainName);
- }
-
- if(FilePart((STRPTR)args[0]) != (STRPTR)args[0])
- printf("%s:%d:Database name \"%s\" contains path specifiers\n",file,line,args[0]);
- }
- }
-
- if(strcmp(found,"@toc") == SAME)
- {
- struct EntryNode *node;
-
- node = CreateNode((char *)args[0]);
- if(node != NULL)
- {
- node->line = line;
- node->within = lastNode;
-
- AddTail(&TocList,(struct Node *)node);
- }
- }
-
- if(strcmp(found,"@index") == SAME)
- {
- struct EntryNode *node;
-
- node = CreateNode((char *)args[0]);
- if(node != NULL)
- {
- node->line = line;
- node->within = lastNode;
-
- AddTail(&IndexList,(struct Node *)node);
- }
- }
- }
- else
- {
- if(strcmp(found,LINK))
- {
- char errorBuffer[400];
-
- Fault(IoErr(),NULL,errorBuffer,sizeof(errorBuffer));
- printf("%s:%d:%s: %s\n",file,line,found,errorBuffer);
- }
- }
-
- FreeArgs(rdargs);
- FreeDosObject(DOS_RDARGS,rdargs);
- }
-
- signal(SIGINT,SIG_DFL);
- }
-
- if(strcmp(found,"@endnode") == SAME)
- {
- if(lastNode != NULL)
- {
- lastNode = NULL;
- }
- else
- {
- printf("%s:%d:Unbalanced @endnode\n",file,line);
- }
- }
-
- if(strcmp(found,LINK) == SAME)
- {
- int i,quote = 0,brace = 1;
-
- for(i = 2 ; i < len ; i++)
- {
- if(buffer[i] == '\"')
- {
- quote ^= 1;
- }
- else
- {
- if(quote == 0)
- {
- if(buffer[i] == OPEN_BRACE) /* open brace */
- brace++;
-
- if(buffer[i] == CLOSE_BRACE) /* closing brace */
- brace--;
-
- if(brace == 0)
- break;
- }
- }
- }
-
- if(brace > 0)
- printf("%s:%d:Missing closing brace in button declaration\n",file,line);
-
- if(brace < 0)
- printf("%s:%d:Unbalanced open brace in button declaration\n",file,line);
-
- if(quote > 0)
- printf("%s:%d:Missing quote in button declaration\n",file,line);
- }
- }
- }
- }
-
- fseek(in,0,SEEK_SET);
-
- line = 0;
-
- while(fgets(buffer,sizeof(buffer)-1,in) != NULL)
- {
- line++;
-
- len = strlen(buffer);
- if(len > 0 && buffer[len - 1] == '\n')
- buffer[--len] = '\0';
-
- if(len > 0)
- {
- int i,quote = 0;
-
- for(i = 0 ; i < len ; i++)
- {
- if(buffer[i] == '@' && buffer[i+1] == '@')
- {
- if(Warnings)
- printf("%s:%d:\"%c\" character escaped in column %d\n",file,line,buffer[i],i+1);
-
- buffer[i] = buffer[i+1] = ' ';
- }
-
- if(buffer[i] == '\\' && i < len-1)
- {
- if(Warnings)
- printf("%s:%d:\"\\%c\" escape sequence in column %d\n",file,line,buffer[i+1],i+1);
-
- buffer[i] = buffer[i+1] = '-';
- }
- }
-
- for(i = 0 ; i < len ; )
- {
- /* if(buffer[i] == '\"')*/
- /* quote ^= 1;*/
-
- if(!quote && buffer[i] == '@' && buffer[i+1] == OPEN_BRACE)
- {
- int j,quote = 0,brace = 1,total;
-
- buffer[i] = ' ';
-
- for(j = i+2, total = 2 ; j < len ; j++, total++)
- {
- if(buffer[j] == '\"')
- {
- quote ^= 1;
- }
- else
- {
- if(quote == 0)
- {
- if(buffer[j] == OPEN_BRACE)
- brace++;
-
- if(buffer[j] == CLOSE_BRACE)
- brace--;
-
- if(brace == 0)
- {
- total++;
- break;
- }
- }
- }
- }
-
- if(brace == 0 && quote == 0)
- {
- static char *style[] =
- {
- "amigaguide",
- "b",
- "body",
- "cleartabs",
- "code",
- "fontn",
- "heading",
- "i",
- "jcenter",
- "jleft",
- "jright",
- "lindent",
- "line",
- "mono",
- "par",
- "pard",
- "pari",
- "plain",
- "prop",
- "settabs",
- "tab",
- "u",
- "ub",
- "ui",
- "uu",
- NULL
- };
- BOOL known = FALSE;
- int k,len;
- char *skip;
-
- skip = &buffer[i+2];
- len = total-3;
-
- while(*skip == ' ' && len > 0)
- {
- skip++;
- len--;
- }
-
- if(len > 0)
- strncpy(localBuffer,skip,len);
- localBuffer[len] = '\0';
-
- for(k = 0 ; style[k] != NULL ; k++)
- {
- if(stricmp(localBuffer,style[k]) == SAME)
- {
- if(stricmp(style[k],"u") == SAME)
- {
- if(underlineCol != -1)
- printf("%s:%d:Unbalanced @{%s} in column %d\n",file,underlineRow,style[k],underlineCol);
-
- underlineCol = i+1;
- underlineRow = line;
- }
-
- if(stricmp(style[k],"uu") == SAME)
- {
- if(underlineCol == -1)
- printf("%s:%d:Command @{%s} in column %d has no effect\n",file,line,style[k],i+1);
-
- underlineCol = -1;
- underlineRow = -1;
- }
-
- if(stricmp(style[k],"b") == SAME)
- {
- if(boldCol != -1)
- printf("%s:%d:Unbalanced @{%s} in column %d\n",file,boldRow,style[k],boldCol);
-
- boldCol = i+1;
- boldRow = line;
- }
-
- if(stricmp(style[k],"ub") == SAME)
- {
- if(boldCol == -1)
- printf("%s:%d:Command @{%s} in column %d has no effect\n",file,line,style[k],i+1);
-
- boldCol = -1;
- boldRow = -1;
- }
-
- if(stricmp(style[k],"i") == SAME)
- {
- if(italicsCol != -1)
- printf("%s:%d:Unbalanced @{%s} in column %d\n",file,italicsRow,style[k],italicsCol);
-
- italicsCol = i+1;
- italicsRow = line;
- }
-
- if(stricmp(style[k],"ui") == SAME)
- {
- if(italicsCol == -1)
- printf("%s:%d:Command @{%s} in column %d has no effect\n",file,line,style[k],i+1);
-
- italicsCol = -1;
- italicsRow = -1;
- }
-
- known = TRUE;
- break;
- }
- }
-
- if(NOT known)
- {
- static char *colourControl[] =
- {
- "fg",
- "apen",
- "bg",
- "bpen",
- NULL
- };
-
- char *rest = NULL;
-
- for(k = 0 ; colourControl[k] != NULL ; k++)
- {
- if(strnicmp(localBuffer,colourControl[k],strlen(colourControl[k])) == SAME)
- {
- rest = &localBuffer[strlen(colourControl[k])];
- break;
- }
- }
-
- if(rest != NULL)
- {
- known = TRUE;
-
- if(rest[0] != ' ')
- printf("%s:%d:Invalid colour control string \"%s\"\n",file,line,rest);
- else
- {
- static char *pens[] =
- {
- "text",
- "shine",
- "shadow",
- "fill",
- "filltext",
- "back",
- "background",
- "highlight",
- NULL
- };
-
- BOOL found = FALSE;
-
- while(*rest == ' ')
- rest++;
-
- for(k = 0 ; pens[k] != NULL ; k++)
- {
- if(stricmp(rest,pens[k]) == SAME)
- {
- found = TRUE;
- break;
- }
- }
-
- if(NOT found)
- printf("%s:%d:Invalid colour \"%s\"\n",file,line,rest);
- }
- }
- }
-
- signal(SIGINT,SIG_IGN);
-
- if(NOT known)
- rdargs = AllocDosObjectTagList(DOS_RDARGS,NULL);
- else
- rdargs = NULL;
-
- if(rdargs != NULL)
- {
- long args[4] = { NULL,NULL,NULL,NULL };
- int k;
-
- strcat(localBuffer,"\n");
-
- rdargs->RDA_Source.CS_Buffer = localBuffer;
- rdargs->RDA_Source.CS_Length = strlen(rdargs->RDA_Source.CS_Buffer);
- rdargs->RDA_Source.CS_CurChr = 0;
- rdargs->RDA_Flags = RDAF_NOPROMPT;
-
- for(k = 0 ; k < strlen(localBuffer) ; k++)
- {
- if(localBuffer[k] == '*') /* This confuses the ReadArgs() parser. */
- localBuffer[k] = '+';
- }
-
- if(ReadArgs("1TEXT/A,2COMMAND/A,3ARG,4ARG",args,rdargs))
- {
- char *name = (char *)args[1];
- char *arg1 = (char *)args[2];
- char *arg2 = (char *)args[3];
-
- if(localBuffer[0] != '\"' || localBuffer[1 + strlen((char *)args[0])] != '\"')
- printf("%s:%d:Button label \"%s\" must be enclosed in quotes\n",file,line,args[0]);
-
- if(stricmp(name,"alink") == SAME)
- {
- if(arg1 == NULL || (arg1 != NULL && *arg1 == '\0'))
- printf("%s:%d:ALINK node name required\n",file,line);
- else
- {
- struct EntryNode *found;
-
- found = (struct EntryNode *)FindIName(&NodeList,arg1);
-
- if(found)
- {
- found->references++;
- }
- else
- {
- struct DatabaseNode *otherNode;
-
- otherNode = LocateNode(parentFile,file,line,(char *)arg1);
- if(otherNode != NULL && Recursive && !otherNode->checked)
- {
- FILE *in;
-
- in = fopen(otherNode->Node.ln_Name,"r");
- if(in != NULL)
- {
- otherNode->checked = TRUE;
- CheckGuide(otherNode->Node.ln_Name,parentFile,in);
-
- fclose(in);
- }
- else
- {
- perror(otherNode->Node.ln_Name);
- }
- }
-
- if(otherNode == NULL)
- printf("%s:%d:Reference to undefined node \"%s\"\n",file,line,arg1);
- }
- }
-
- if(arg2 != NULL)
- {
- if(!IsNumber(arg2))
- printf("%s:%d:ALINK line number invalid\n",file,line);
- }
- }
- else if (!stricmp(name,"close"))
- {
- if(arg1 != NULL && arg2 != NULL)
- printf("%s:%d:Too many arguments for CLOSE command\n",file,line);
- }
- else if (!stricmp(name,"link"))
- {
- if(arg1 == NULL || (arg1 != NULL && *arg1 == '\0'))
- printf("%s:%d:LINK node name required\n",file,line);
- else
- {
- struct EntryNode *found;
-
- found = (struct EntryNode *)FindIName(&NodeList,arg1);
-
- if(found)
- {
- found->references++;
- }
- else
- {
- struct DatabaseNode *otherNode;
-
- otherNode = LocateNode(parentFile,file,line,(char *)arg1);
- if(otherNode != NULL && Recursive && !otherNode->checked)
- {
- FILE *in;
-
- in = fopen(otherNode->Node.ln_Name,"r");
- if(in != NULL)
- {
- otherNode->checked = TRUE;
- CheckGuide(otherNode->Node.ln_Name,parentFile,in);
-
- fclose(in);
- }
- else
- {
- perror(otherNode->Node.ln_Name);
- }
- }
-
- if(otherNode == NULL)
- printf("%s:%d:Reference to undefined node \"%s\"\n",file,line,arg1);
- }
- }
-
- if(arg2 != NULL)
- {
- if(!IsNumber(arg2))
- printf("%s:%d:LINK line number invalid\n",file,line);
- }
- }
- else if (!stricmp(name,"rx"))
- {
- if(arg1 == NULL || (arg1 != NULL && *arg1 == '\0'))
- printf("%s:%d:RX command required\n",file,line);
- }
- else if (!stricmp(name,"rxs"))
- {
- if(arg1 == NULL || (arg1 != NULL && *arg1 == '\0'))
- printf("%s:%d:RXS command required\n",file,line);
- }
- else if (!stricmp(name,"system"))
- {
- if(arg1 == NULL || (arg1 != NULL && *arg1 == '\0'))
- printf("%s:%d:SYSTEM command required\n",file,line);
- }
- else if (!stricmp(name,"quit"))
- {
- if(arg1 != NULL && arg2 != NULL)
- printf("%s:%d:Too many arguments for QUIT command\n",file,line);
- }
- else
- {
- printf("%s:%d:Unknown link command \"%s\"\n",file,line,name);
- }
- }
- else
- {
- char errorBuffer[400];
-
- Fault(IoErr(),NULL,errorBuffer,sizeof(errorBuffer));
- printf("%s:%d:link: %s\n",file,line,errorBuffer);
- }
-
- FreeArgs(rdargs);
- FreeDosObject(DOS_RDARGS,rdargs);
- }
-
- signal(SIGINT,SIG_DFL);
- }
-
- if(quote > 0)
- {
- printf("%s:%d:Unbalanced quote in button declaration at column %d\n",file,line,i+1);
- }
-
- if(brace > 0)
- {
- printf("%s:%d:Unbalanced brace in button declaration at column %d\n",file,line,i+1);
- }
-
- i += total;
- }
- else
- {
- if(!quote && buffer[i] == '@')
- {
- int j;
- char const *found = NULL;
-
- for(j = 0 ; keywords[j][0] != NULL ; j++)
- {
- if(strnicmp(&buffer[i],keywords[j][0],strlen(keywords[j][0])) == SAME)
- {
- found = keywords[j][0];
- break;
- }
- }
-
- if(found)
- buffer[i] = ' ';
-
- if(found && i > 0)
- {
- printf("%s:%d:Command \"%s\" has no effect\n",file,line,found);
- }
-
- if(found && i == 0)
- {
- if(strcmp(found,"@next") == SAME || strcmp(found,"@prev") == SAME)
- {
- STRPTR nodeName = NULL;
- char *skip;
-
- skip = &buffer[strlen(found)];
- while(*skip == ' ')
- skip++;
-
- signal(SIGINT,SIG_IGN);
-
- rdargs = AllocDosObjectTagList(DOS_RDARGS,NULL);
- if(rdargs != NULL)
- {
- int k;
-
- strcat(skip,"\n");
-
- rdargs->RDA_Source.CS_Buffer = skip;
- rdargs->RDA_Source.CS_Length = strlen(rdargs->RDA_Source.CS_Buffer);
- rdargs->RDA_Source.CS_CurChr = 0;
- rdargs->RDA_Flags = RDAF_NOPROMPT;
-
- for(k = 0 ; k < strlen(skip) ; k++)
- {
- if(skip[k] == '*') /* This confuses the ReadArgs() parser. */
- skip[k] = '+';
- }
-
- if(ReadArgs("1NODE/A",(LONG *)&nodeName,rdargs))
- {
- struct EntryNode *node;
-
- node = (struct EntryNode *)FindIName(&NodeList,nodeName);
- if(node != NULL)
- {
- node->references++;
- }
- else
- {
- struct DatabaseNode *otherNode;
-
- otherNode = LocateNode(parentFile,file,line,nodeName);
- if(otherNode != NULL && Recursive && !otherNode->checked)
- {
- FILE *in;
-
- in = fopen(otherNode->Node.ln_Name,"r");
- if(in != NULL)
- {
- otherNode->checked = TRUE;
- CheckGuide(otherNode->Node.ln_Name,parentFile,in);
-
- fclose(in);
- }
- else
- {
- perror(otherNode->Node.ln_Name);
- }
- }
-
- if(otherNode == NULL)
- printf("%s:%d:%s references undefined node \"%s\"\n",file,line,found,nodeName);
- }
- }
- else
- {
- char errorBuffer[400];
-
- Fault(IoErr(),NULL,errorBuffer,sizeof(errorBuffer));
- printf("%s:%d:%s: %s\n",file,line,found,errorBuffer);
- }
-
- FreeArgs(rdargs);
- FreeDosObject(DOS_RDARGS,rdargs);
- }
-
- signal(SIGINT,SIG_DFL);
- }
- }
-
- if(NOT found && buffer[i+1] == ' ')
- {
- char *rest = &buffer[i+1];
-
- while(*rest == ' ')
- rest++;
-
- if(*rest == OPEN_BRACE)
- printf("%s:%d:Incomplete/invalid link declaration\n",file,line);
- }
- }
-
- i++;
- }
- }
-
- for(i = 0 ; i < len ; i++)
- {
- if(buffer[i] == '@' || buffer[i] == '\\')
- printf("%s:%d:Single \"%c\" character in column %d\n",file,line,buffer[i],i + 1);
- }
- }
- }
-
- if(underlineCol != -1)
- printf("%s:%d:Unbalanced @{%s} in column %d\n",file,underlineRow,"u",underlineCol);
-
- if(boldCol != -1)
- printf("%s:%d:Unbalanced @{%s} in column %d\n",file,boldRow,"b",boldCol);
-
- if(italicsCol != -1)
- printf("%s:%d:Unbalanced @{%s} in column %d\n",file,italicsRow,"i",italicsCol);
-
- mainFound = (struct EntryNode *)FindIName(&NodeList,"main");
- if(mainFound)
- mainFound->references++;
- else
- printf("%s:%d:MAIN node missing\n",file,1);
-
- if(NOT IsListEmpty(&TocList))
- {
- struct EntryNode *found;
- int mainContext = 0;
-
- for(node = (struct EntryNode *)TocList.lh_Head ; node->Node.ln_Succ ; node = (struct EntryNode *)node->Node.ln_Succ)
- {
- found = (struct EntryNode *)FindIName(&NodeList,node->Node.ln_Name);
- if(found)
- found->references++;
- else
- {
- struct DatabaseNode *otherNode;
-
- otherNode = LocateNode(parentFile,file,node->line,(char *)node->Node.ln_Name);
- if(otherNode != NULL && Recursive && !otherNode->checked)
- {
- FILE *in;
-
- in = fopen(otherNode->Node.ln_Name,"r");
- if(in != NULL)
- {
- otherNode->checked = TRUE;
- CheckGuide(otherNode->Node.ln_Name,parentFile,in);
-
- fclose(in);
- }
- else
- {
- perror(otherNode->Node.ln_Name);
- }
- }
-
- if(otherNode == NULL)
- printf("%s:%d:TOC node \"%s\" missing\n",file,node->line,node->Node.ln_Name);
- }
-
- if(node->within == NULL)
- {
- if(mainContext++ > 0)
- printf("%s:%d:More than one @TOC at top level\n",file,node->line);
- }
- }
-
- FreeList(&TocList);
- }
-
- if(NOT IsListEmpty(&IndexList))
- {
- struct EntryNode *found;
- int mainContext = 0;
-
- for(node = (struct EntryNode *)IndexList.lh_Head ; node->Node.ln_Succ ; node = (struct EntryNode *)node->Node.ln_Succ)
- {
- found = (struct EntryNode *)FindIName(&NodeList,node->Node.ln_Name);
- if(found)
- found->references++;
- else
- {
- struct DatabaseNode *otherNode;
-
- otherNode = LocateNode(parentFile,file,node->line,(char *)node->Node.ln_Name);
- if(otherNode != NULL && Recursive && !otherNode->checked)
- {
- FILE *in;
-
- in = fopen(otherNode->Node.ln_Name,"r");
- if(in != NULL)
- {
- otherNode->checked = TRUE;
- CheckGuide(otherNode->Node.ln_Name,parentFile,in);
-
- fclose(in);
- }
- else
- {
- perror(otherNode->Node.ln_Name);
- }
- }
-
- if(otherNode == NULL)
- printf("%s:%d:INDEX node \"%s\" missing\n",file,node->line,node->Node.ln_Name);
- }
-
- if(node->within == NULL)
- {
- if(mainContext++ > 0)
- printf("%s:%d:More than one @INDEX at top level\n",file,node->line);
- }
- }
-
- FreeList(&IndexList);
- }
-
- for(node = (struct EntryNode *)NodeList.lh_Head ; node->Node.ln_Succ ; node = (struct EntryNode *)node->Node.ln_Succ)
- {
- if(node->references == 0)
- printf("%s:%d:Unused @node \"%s\"\n",file,node->line,node->Node.ln_Name);
- }
-
- FreeList(&NodeList);
- }
-
- /****************************************************************************/
-
- int
- main(int argc,char **argv)
- {
- if(DOSBase->lib_Version >= 36)
- {
- if(argc > 1 && !(argc == 2 && argv[1][0] == '?'))
- {
- FILE * in;
- int i;
-
- NewList(&CheckedFileList);
-
- for(i = 1 ; i < argc ; i++)
- {
- if(stricmp(argv[i],"-r") == SAME || stricmp(argv[i],"--recursive") == SAME)
- {
- Recursive = TRUE;
- continue;
- }
-
- if(stricmp(argv[i],"-o") == SAME || stricmp(argv[i],"--onlyguidefiles") == SAME)
- {
- OnlyGuideFiles = TRUE;
- continue;
- }
-
- if(stricmp(argv[i],"-w") == SAME || stricmp(argv[i],"--nowarnings") == SAME)
- {
- Warnings = FALSE;
- continue;
- }
-
- in = fopen(argv[i],"r");
- if(in != NULL)
- {
- BPTR lock;
-
- lock = Lock(argv[i],SHARED_LOCK);
- if(lock != NULL)
- {
- struct DatabaseNode *node;
-
- node = RegisterFile(&CheckedFileList,lock);
-
- UnLock(lock);
-
- if(node != NULL)
- {
- node->checked = TRUE;
- CollectNodes(node->Node.ln_Name,&node->nodes);
- }
- }
-
- CheckGuide(argv[i],argv[i],in);
-
- fclose(in);
- }
- else
- {
- perror(argv[i]);
- }
- }
-
- FreeList(&CheckedFileList);
- }
- else
- {
- printf("Usage: checkguide [-r,--recursive] [-o,--onlyguidefiles] [-w,--nowarnings]\n");
- printf(" <files>\n");
- }
- }
-
- return(0);
- }
-